/*
 * PsFileStream.h
 *
 *  Created on: 2018年7月8日
 *      Author: zhengboyuan
 */

#ifndef PSFILESTREAM_H_
#define PSFILESTREAM_H_

#include "PsHeader.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <string.h>
#include <time.h>

#include "TByteBuffer.h"

/// PS包类型
enum PsPacketType
{
    kPsUnknown = 0,
    kPsPackHeader,
    kPsSystemHeader,
    kPsPsmHeader,
    kPsAudioPacket,
    kPsVideoPacket
};

/// PS包
struct PsPacket
{
    PsPacketType type;  /// 类型
    int64_t pos;        /// 文件偏移
    uint8_t* data;      /// 包数据指针
    int size;           /// 包长度
};


/// PS文件流, 读取PS包
class PsFileStream
{
public:
    /// 从PS包中读取PES流数据, 返回false 表示不是PES包
    static bool getPesData(PsPacket& pkt, PsPacket& out);

    /// 从PS包中获取扩展时间
    static bool getTime(PsPacket& pkt, time_t& t);

    /// 从PS包中获取时间戳
    static bool getTimeStamp(PsPacket& pkt, int64_t& pts, int64_t& dts);

public:
    PsFileStream();
    virtual ~PsFileStream();

    /// 打开文件
    bool open(const char* filepath);

    /// 关闭文件
    void close();

    /// 文件是否已打开
    bool isOpen();

    /// 获取当前文件偏移
    int64_t tellg();

    /// 定位到指定偏移
    bool seekg(int64_t pos);

    /// 文件是否结束
    bool eof();

    /// 读取PS包, 返回false表示文件结束
    bool read(PsPacket& pkt);

    /// 获取文件路径
    const std::string& getFilePath() const;

    /// 获取上次解析出来的扩展时间
    time_t getLastTime();

    /// 获取上次解析的包
    PsPacket getLastPacket();

    /// 获取当前的扩展时间
    time_t getCurTime();

    /// 获取当前解析的包
    PsPacket getCurPacket();

public:
    /// 读取指定长度的数据到缓冲区
    bool read(int size, comn::ByteBuffer& buffer);


protected:

    enum State
    {
        kStart = 0,
        kSingleZero,
        kDoubleZero,
        kStartCode,
        kPackHeader,
        kSystemHeader,
        kPsmHeader,
        kPesAudioPacket,
        kPesVideoPacket,
        kUnknownPacket,
    };

    bool handleByte(uint8_t ch, PsPacket& pkt);

    int readToBuffer(comn::ByteBuffer& buffer, int size);

    void buildPacket(PsPacket& pkt, PsPacketType type);

protected:
    std::string m_filepath;
    std::ifstream   m_ifs;

    comn::ByteBuffer    m_buffer;

    State   m_state;
    int64_t m_pos;

    PsPacket    m_curPacket;
    time_t      m_curTime;

    PsPacket    m_lastPacket;
    time_t      m_lastTime;
};

#endif /* PSFILESTREAM_H_ */
